package com.pic.mgt.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.xml.XMLConstants;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axis2.util.XMLUtils;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;


public abstract class XMLProcessUtils {
	/**
	 * 剖析(驗證) XML 檔
	 * 
	 * @param xmlFile			要剖析的 xml 檔案
	 * @param xmlSchemaFile		Schema 驗證(可為 null)
	 * 
	 * @throws XMLStreamException	  XML 檔案內容格式錯誤
	 * @throws OMELement2DOMException Apache OMElement 轉 W3C DOM 錯誤
	 * @throws SAXException 		  XML 檔內容不符 Schema 規範
	 * 
	 * @return OMElement 回傳為分析過後的 root element
	 */
	public static OMElement parseXMLFile(File xmlFile, File xmlSchemaFile) throws XMLStreamException, SAXException, IOException, Exception {		
		// XMLStreamException
		XMLStreamReader parser = 
					XMLInputFactory.newInstance().createXMLStreamReader(
					new FileInputStream(xmlFile));		
		StAXOMBuilder builder = new StAXOMBuilder(parser);
		//取得頂層元素
		OMElement documentElement = builder.getDocumentElement();
		
		// 驗證 xml 是否符合 XML Schema；
		if (xmlSchemaFile != null) {
			// throws OMElement2DOMException,SAXException,IOException				      
			validateXMLBySchema(documentElement, xmlSchemaFile);
		}
		
		return documentElement;
	}
	
	public static OMElement parseXMLFile(String xmlFileStr, String xmlSchemaFileStr) throws XMLStreamException, SAXException, IOException, Exception {
		File xmlFile = new File(xmlFileStr);
		File xmlSchemaFile = new File(xmlSchemaFileStr);
		
		return parseXMLFile(xmlFile, xmlSchemaFile);
	}
	
	/*
	 * 驗證 XML 是否符合 Schema 規範
	 */
	private static void validateXMLBySchema(OMElement xmlDocument, File xmlSchemaFile)  throws SAXException, IOException, Exception {
		Element sourceElement;
		
		// 須先將 OMElement 轉為 W3C DOM ，才能餵給java validator api
		// throws Exception
		sourceElement = XMLUtils.toDOM(xmlDocument);
		
		SchemaFactory factory =
			SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
		Source source = new StreamSource(xmlSchemaFile);
		// throws SAXException
		Schema schema = factory.newSchema(source);
		Validator validator = schema.newValidator();
		// throws IOException, SAXException
		validator.validate(new DOMSource(sourceElement));
	}
}
